import { Stage } from 'babylon-lib/base/stage';
import * as Data from '../data/data';
import { CreateUINode, UINode } from 'babylon-lib/gui/base/ui-node';
import { Vector3 } from '@babylonjs/core/Maths/math.vector';
import { CreateUIRectangle } from 'babylon-lib/gui/control/ui-rectangle';
import { CreateUISlider, IUISliderOptions, UISlider } from 'babylon-lib/gui/control/ui-slider';
import { RenderOrder } from 'babylon-lib/misc/render-order';
import { ANCHOR } from 'babylon-lib/gui/control/abstract-base';
import { Calculation, DEGREE } from 'babylon-lib/tool/calculation';
import { CreateUIButton } from 'babylon-lib/gui/control/ui-button';
import { DefaultStage } from '../stage/default-stage';
import { Helper } from 'babylon-lib/tool/helper';
import { RawAssetsUrl } from '../raw-assets-info';
import { GLTFMeshTaskInfo, TransformNode } from 'babylon-lib/index';
import { DefaultModel } from '../stage/default-stage-component/default-model';
import { ModelContainer } from '../stage/default-stage-component/model-container';
import { AnimationGroup } from '@babylonjs/core/Animations/animationGroup';


class ControlPanel {

    private static _posX: UISlider;
    private static _posY: UISlider;
    private static _posZ: UISlider;
    private static _rotX: UISlider;
    private static _rotY: UISlider;
    private static _rotZ: UISlider;
    private static _scl: UISlider;
    private static _lgt: UISlider;

    public static node: UINode;

    public static initialize(stage: Stage): void {
        this.initializeNode(stage);
    }

    public static reset(): void {
        this._posX.value = 0;
        this._posY.value = 0;
        this._posZ.value = 0;
        this._rotX.value = 0;
        this._rotY.value = 0;
        this._rotZ.value = 0;
        this._scl.value = 0;
        this._lgt.value = 0;
    }

    private static initializeNode(stage: Stage): void {
        const sliderStyle: IUISliderOptions = {
            anchor: ANCHOR.RIGHT_TOP,
            width: 4.2,
            height: 0.45,
            titleWidth: 60,
            fontColor: '#cecece',
            fontSize: 18,
            sliderWidth: 200,
            range: [-100, 100],
            step: 0.01,
            sliderThumbColor: '#cecece',
            showValue: false,
            renderingGroupId: RenderOrder.id(Data.orders.ui),
        }
        const ofs = -0.01;
        const space = 0.04;

        this.node = CreateUINode('control-panel-node', stage.mainScene, {
            anchor: new Vector3(1, 0, 0),
            lockToCamera: true,
            xrRatio: { x: 0.6, y: 0.6 },
        }, [
            CreateUIRectangle('control-panel-background', stage.mainScene, {
                anchor: ANCHOR.RIGHT_TOP,
                renderingGroupId: RenderOrder.id(Data.orders.uiBack),
                width: 4.4,
                height: 4.1,
                alpha: 0.4,
                cornerRadius: 5,
                inoperable: true,
            }),
            this._posX = CreateUISlider('control-panel-pos-x', stage.mainScene, {
                title: '平移\tX',
                top: ofs,
                ...sliderStyle,
            }, (value) => {
                Data.positionX.value = value;
            }),
            this._posY = CreateUISlider('control-panel-pos-y', stage.mainScene, {
                title: '\t\t\t\t\t\t\t\tY',
                top: ofs - space,
                ...sliderStyle,
            }, (value) => {
                Data.positionY.value = value;
            }),
            this._posZ = CreateUISlider('control-panel-pos-z', stage.mainScene, {
                title: '\t\t\t\t\t\t\t\tZ',
                top: ofs - space * 2,
                ...sliderStyle,
            }, (value) => {
                Data.positionZ.value = value;
            }),
            this._rotX = CreateUISlider('control-panel-rot-x', stage.mainScene, {
                title: '旋转\tX',
                top: ofs - space * 3,
                ...sliderStyle,
            }, (value) => {
                const val = Calculation.valueLinearMapping(value, -100, 100, [-100, -360 * DEGREE, 0, 0, 100, 360 * DEGREE]);
                Data.rotationX.value = val;
            }),
            this._rotY = CreateUISlider('control-panel-rot-y', stage.mainScene, {
                title: '\t\t\t\t\t\t\t\tY',
                top: ofs - space * 4,
                ...sliderStyle,
            }, (value) => {
                const val = Calculation.valueLinearMapping(value, -100, 100, [-100, -360 * DEGREE, 0, 0, 100, 360 * DEGREE]);
                Data.rotationY.value = val;
            }),
            this._rotZ = CreateUISlider('control-panel-rot-z', stage.mainScene, {
                title: '\t\t\t\t\t\t\t\tZ',
                top: ofs - space * 5,
                ...sliderStyle,
            }, (value) => {
                const val = Calculation.valueLinearMapping(value, -100, 100, [-100, -360 * DEGREE, 0, 0, 100, 360 * DEGREE]);
                Data.rotationZ.value = val;
            }),
            this._scl = CreateUISlider('control-panel-scl', stage.mainScene, {
                title: '缩放',
                top: ofs - space * 6,
                ...sliderStyle,
            }, (value) => {
                const val = Calculation.valueLinearMapping(value, -100, 100, [-100, 0.001, 0, 1, 100, 100]);
                Data.scale.value = val;
            }),
            this._lgt = CreateUISlider('control-panel-light', stage.mainScene, {
                title: '灯光',
                top: ofs - space * 7,
                ...sliderStyle,
            }, (value) => {
                const val = Calculation.valueLinearMapping(value, -100, 100, [-100, 0, 0, 1, 100, 10]);
                Data.lightIntensity.value = val;
            }),
            CreateUIButton('control-panel-upload-button', stage.mainScene, {
                anchor: ANCHOR.RIGHT_TOP,
                text: '上传GLTF模型',
                top: ofs - space * 8.5,
                width: 3,
                left: -0.06,
                height: 0.45,
                fontSize: 17,
                renderingGroupId: RenderOrder.id(Data.orders.ui),
            }, () => {
                const stg = stage as DefaultStage;
                if (Helper.isImmersive(stg.mainScene)) {
                    stg.vr?.helper.exitXRAsync().then(() => {
                        this.upload(stg);
                    });
                } else {
                    this.upload(stg);
                }
            }),
        ]);
    }

    private static upload(stage: DefaultStage): void {
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = '.glb,.gltf';

        input.addEventListener("change", (evt) => {
            const file = (input as any).files[0];
            if (!file) return;
            const name = file.name;
            const ns = name.split('.');
            if (ns[ns.length - 1] !== 'glb') return;
            const url = URL.createObjectURL(file);
            input.remove();

            const scene = stage.mainScene;
            const loader = stage.loader(scene);

            RawAssetsUrl.changjing = url;
            const task = new GLTFMeshTaskInfo(url);
            loader.load({ changjing: task }, undefined, undefined, undefined, () => {
                stage.engine.loadingScreen.hideLoadingUI();
                DefaultModel.display(false);
                const ls = loader.getMeshTaskInfo(RawAssetsUrl.changjing)!;
                if (!ls) return;
                const ms: TransformNode[] = [];
                if (ls.loadedMeshes) {
                    ms.push(...ls.loadedMeshes);
                }
                if (ls.loadedTransformNodes) {
                    ms.push(...ls.loadedTransformNodes);
                }
                for (const m of ms) {
                    if (!m.parent) ModelContainer.setTarget(m);
                }
                if (ls.loadedAnimationGroups) {
                    ls.loadedAnimationGroups.forEach((ag: AnimationGroup) => {
                        ag.play(true);
                    });
                }
            }, undefined);
        });

        input.click();
    }

}


export { ControlPanel };